#ifndef COMMON_H
#define COMMON_H

#include <sys/epoll.h>
#include <fcntl.h>
#include <stdio.h>

// 默认服务器端IP地址
#define SERVER_IP "127.0.0.1"

// 服务器端口号
#define SERVER_PORT 8888

// int epoll_create(int size)中的size
// 为epoll支持的最大句柄数
#define EPOLL_SIZE 5000

// 缓冲区大小65535
#define BUF_SIZE 0xFFFF

// 新用户登录后的欢迎信息
#define SERVER_WELCOME "Welcome you join to the chat room! Your chat ID is: Client #%d"

// 其他用户收到消息的前缀
#define SERVER_MESSAGE "ClientID %d say >> %s"
#define SERVER_PRIVATE_MESSAGE "Client %d say to you privately >> %s"
#define SERVER_PRIVATE_ERROR_MESSAGE "Client %d is not in the chat room yet~"
// 退出系统
#define EXIT "EXIT"

// 提醒你是聊天室中唯一的客户
#define CAUTION "There is only one int the char room!"


// 注册新的fd到epollfd中
// 参数enable_et表示是否启用ET模式，如果为True则启用，否则使用LT模式
static void addfd( int epollfd, int fd, bool enable_et )
{

    struct epoll_event epoll;

    // 设置监听事件

    epoll.data.fd = fd;

    epoll.events = EPOLLIN;

    if (enable_et) {
        epoll.events = EPOLLIN | EPOLLET;
    }

    /**
     * @brief epoll_ctl epoll的事件注册函数
     * 第一个参数是epoll_create()的返回值，
        第二个参数表示动作，用三个宏来表示：
        EPOLL_CTL_ADD：       注册新的fd到epfd中；
        EPOLL_CTL_MOD：      修改已经注册的fd的监听事件；
        EPOLL_CTL_DEL：        从epfd中删除一个fd；
        第三个参数是需要监听的fd，
        第四个参数是告诉内核需要监听什么事件
     */
    epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, & epoll);
    // 设置socket为非阻塞模式
    // 套接字立刻返回，不管I/O是否完成，该函数所在的线程会继续运行
    //eg. 在recv(fd...)时，该函数立刻返回，在返回时，内核数据还没准备好会返回WSAEWOULDBLOCK错误代码F_SETFL 设置文件描述符状态旗标，参数arg为新旗标
    // F_GETFD取得close-on-exec旗标。若此旗标的FD_CLOEXEC位为0，代表在调用exec()相关函数时文件将不会关闭
    // https://blog.csdn.net/q1449516487/article/details/90969055
    fcntl(fd, F_SETFL, fcntl(fd, F_GETFD, 0) | O_NONBLOCK);
    printf("fd added to epoll!\n\n");
}

//定义信息结构，在服务端和客户端之间传送
struct Msg
{
    int type;
    int fromID;
    int toID;
    char content[BUF_SIZE];

};
#endif // CHATROOM_COMMON_H

